package net.sk.china.front.service.impl.user;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.sk.china.common.constants.Constants;
import net.sk.china.common.exception.ExceptionCodeEnum;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.model.user.User;
import net.sk.china.common.utils.DateUtil;
import net.sk.china.common.utils.RedisUtil;
import net.sk.china.common.utils.TalkUtil;
import net.sk.china.front.dao.user.UserDao;
import net.sk.china.front.response.SystemAttachmentResponse;
import net.sk.china.front.service.system.SystemConfigService;
import net.sk.china.front.service.user.UserService;
import net.sk.china.front.token.TokenComponent;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * UserServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2018-2024 聊来All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * +----------------------------------------------------------------------
 * | @Author: 聊来 <18970881148@qq.com>
 * +----------------------------------------------------------------------
 * | DateTime: 2024/6/4 14:59
 * +----------------------------------------------------------------------
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Resource
    private UserDao dao;

    @Resource
    private RedisUtil redisUtil;

    private final SystemConfigService systemConfigService;

    private final TokenComponent tokenComponent;

    public UserServiceImpl(SystemConfigService systemConfigService, TokenComponent tokenComponent) {
        this.systemConfigService = systemConfigService;
        this.tokenComponent = tokenComponent;
    }

    /**
     * 根据账号查询用户
     * @param account 账号
     * @return {@code User}
     */
    @Override
    public User getByAccount(String account) {
        LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();
        query.eq(User::getAccount, account);
        query.last("limit 1");

        return dao.selectOne(query);
    }

    /**
     * 创建令牌
     * @param uid 用户ID
     * @return {@code String}
     */
    @Override
    public String createToken(Integer uid) {
        String token = UUID.randomUUID().toString().replace("-", "");
        redisUtil.set(Constants.USER_TOKEN_REDIS_KEY_PREFIX + token, uid, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);

        return token;
    }

    /**
     * 手机号注册用户
     * @param phone 手机号
     * @param loginType 登录类型
     * @param ip 客户端IP
     * @return {@code User}
     */
    @Override
    public User registerPhone(String phone, String loginType, String ip) {
        User user = new User();
        user.setAccount(phone);
        user.setPwd(TalkUtil.createPwd(phone));
        user.setPhone(phone);
        user.setUserType(loginType);
        user.setLoginType(loginType);
        user.setAvatar(getAvatar());
        user.setCreateTime(DateUtil.getNowTime());
        user.setAddIp(ip);
        user.setLastIp(ip);
        user.setLastLoginTime(DateUtil.getNowTime());

        if (dao.insert(user) < 1) {
            throw new TalkException("用户注册失败!");
        }

        return user;
    }

    /**
     * 获取系统随机头像
     * @return {@code String}
     */
    @Override
    public String getAvatar() {
        String avatar = systemConfigService.getValueByKey(net.sk.china.front.constants.Constants.USER_DEFAULT_AVATAR_CONFIG_KEY);

        if (StrUtil.isNotBlank(avatar)) {
            List<SystemAttachmentResponse> attachment = JSONObject.parseArray(avatar, SystemAttachmentResponse.class);
            SecureRandom random = new SecureRandom();
            int next = random.nextInt(attachment.size());
            return attachment.get(next).getSattDir();
        }

        return "";
    }

    /**
     * 账户详情 检测用户异常情况
     * @return {@code User}
     */
    @Override
    public User getUserInfo() {
        Integer uid = tokenComponent.getUserId();
        if (uid == null) {
            throw new TalkException(ExceptionCodeEnum.UNAUTHORIZED.getCode(), ExceptionCodeEnum.UNAUTHORIZED.getMessage());
        }
        User user = dao.selectById(uid);
        if (ObjectUtil.isNull(user)) {
            // 非正常删除操作，导致用户信息没有存储在user表中或redis缓存中
            throw new TalkException("用户信息不存在");
        }

        if (user.getStatus().equals(Constants.NUM_ZERO)) {
            throw new TalkException("账号已经被禁用，请联系系统管理员");
        }

        return user;
    }

    /**
     * 获取个人资料
     * @return {@code User}
     */
    @Override
    public User getInfo() {
        if (getUserId() == 0) {
            return null;
        }
        return dao.selectById(getUserId());
    }

    /**
     * 获取用户ID
     * @return {@code Integer}
     */
    @Override
    public Integer getUserId() {
        User user = getUserInfo();

        return user.getUid();
    }

    /**
     * 更新用户积分
     * @param user 用户
     * @param integral 积分
     * @param type 增加add、扣减sub
     * @return {@code boolean}
     */
    @Override
    public boolean updateIntegral(User user, Integer integral, String type) {
        LambdaUpdateWrapper<User> query = new LambdaUpdateWrapper<>();
        if (type.equals("add")) {
            query.set(User::getIntegral, user.getIntegral() + integral);
        } else {
            query.set(User::getIntegral, user.getIntegral() - integral);
        }
        query.eq(User::getUid, user.getUid());
        if (type.equals("sub")) {
            query.apply(StrUtil.format(" integral - {} >= 0", integral));
        }
        return update(query);
    }

    /**
     * 更新余额
     * @param user 用户
     * @param price 金额
     * @param type 增加add、扣减sub
     * @return {@code boolean}
     */
    @Override
    public boolean updateNowMoney(User user, BigDecimal price, String type) {
        LambdaUpdateWrapper<User> query = new LambdaUpdateWrapper<>();
        if (type.equals("add")) {
            query.set(User::getNowMoney, user.getNowMoney().add(price));
        } else {
            query.set(User::getNowMoney, user.getNowMoney().subtract(price));
        }
        query.eq(User::getUid, user.getUid());
        if (type.equals("sub")) {
            query.apply(StrUtil.format(" now_money - {} >= 0", price));
        }
        return update(query);
    }
}
